package Controlador;

import java.rmi.RemoteException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;



import ControladorPersistencia.AdminCondicionesPago;
import ControladorPersistencia.AdminGanacia;
import ControladorPersistencia.AdminProveedor;
import ControladorPersistencia.AdminRodamiento;
import Dao.ProveedorDao;
import Dao.RodamientoDao;
import Dao.SolicitudRodamientoDAO;
import Negocio.*;
import Negocio.MovimientoStock.TipoMovimiento;

import VO.*;


public class CPR {

	
	
	private SolicitudCompraCPR solicitudcompra;
	private Vector<RemitoProveedor> remitosproveedor;
	private Vector<Rodamiento> rodamientos;
	private Vector<Proveedor> proveedores;
	private Vector<RemitoPRV> remitosprv;
	private Vector<ListaPreciosCPR> listasprecios; 

	
	
	public CPR() {
		super();
		this.proveedores=new Vector<Proveedor>();
		this.rodamientos= new Vector<Rodamiento>();
		this.listasprecios = new Vector<ListaPreciosCPR>();
	}

	public void altaRodamiento(RodamientoVO rodVO)
	{
		Rodamiento rod = buscarRodamiento(rodVO);
		if(rod == null)
		{

			String codigo=rodVO.getCodigo();
			String descripcion=rodVO.getDescripcion();
			float medida=rodVO.getMedida();
			
			String modelo=rodVO.getModelo();
			Stock stock= new Stock(0,rodVO.getStock().getPuntoRep());
			stock.addMovimientoAlta(rodVO.getStock().getCantidad());
			rod = new Rodamiento(codigo, descripcion,  medida, modelo, stock);
			// guardo el rodamiento
			rodamientos.add(rod);
			AdminRodamiento.getInstance().grabarRodamiento(rod);
		}
	}
	
	// rodamiento existe y se modifica el stock
	public void actualizarStock(RodamientoVO rodVO, MovimientoStockVO mv) throws Exception 
	{
		Rodamiento rod=buscarRodamiento(rodVO);
		if(rod!=null)
		{
			if(mv.getTipo()==VO.MovimientoStockVO.TipoMovimiento.ALTA)
				rod.getStock().addMovimientoAlta(mv.getCant());
			if(mv.getTipo()==VO.MovimientoStockVO.TipoMovimiento.BAJA)
				rod.getStock().addMovimientoBaja(mv.getCant());
			
			AdminRodamiento.getInstance().modificarRodamiento(rod);
		}
		
		throw new Exception("Rodamiento no existente");
	}
	
	public void eliminarRodamiento(RodamientoVO rodVO) throws Exception //rodamiento existe 
	{
		Rodamiento rod=buscarRodamiento(rodVO);
		if(rod!=null)
		{
			rodamientos.remove(rod);
			AdminRodamiento.getInstance().borrarRodamiento(rod.getId());
		}
		throw new Exception("Rodamiento no existente");
	}
	
	
	private Rodamiento buscarRodamientoLocal(RodamientoVO vo)
	{
		Rodamiento p ;
		Iterator<Rodamiento> it = rodamientos.iterator();
		while(it.hasNext()){
			p= it.next();
			if(p.getCodigo()== vo.getCodigo())
			{
				return p;
			}
		}
		return null;
	}
	
	public Rodamiento buscarRodamiento(RodamientoVO vo) {
		Rodamiento p = null ; //buscarRodamientoLocal(vo);
		if(p==null)
		{
			if(vo.getId()!=-1)
			{	System.out.println("Rodamiento buscado por id");
				p= AdminRodamiento.getInstance().buscarRodamiento(vo.getId());
			}else 
				if(vo.getCodigo()!=null)
				{
					System.out.println("Rodamiento buscado por codigo:"+vo.getCodigo());
					p=  AdminRodamiento.getInstance().buscarRodamiento(vo.getCodigo());
				}
			//if(p!=null ) rodamientos.add(p);
		}
		return p;
	}

	//TODO se usa internamente para encontrar rodamientos. no tendria que ser privada?
	public Rodamiento buscarRodamiento(String codigo)
	{
		return AdminRodamiento.getInstance().buscarRodamiento(codigo);
	}
	

	
	public void altaProveedor(ProveedorVO prov)
	{
		Proveedor p = buscarProveedor(prov);
		if(p == null)
		{
			String nombre = prov.getNombre();
			String cuit = prov.getCuit();
			String condicionCompra = prov.getCondicionCompra();
			float descuento = prov.getDescuento();
			String direccion = prov.getDireccion();
			String telefono = prov.getTelefono();
			p=new Proveedor(nombre, cuit, condicionCompra, descuento, direccion, telefono);
			
			//proveedores.add(p);
			AdminProveedor.getInstance().grabarProveedor(p);
		}
	}
	
	public ProveedorVO proveedorToVO(Proveedor p)
	{
		if(p==null)
			return null;
		ProveedorVO pv=new ProveedorVO();
		pv.setCondicionCompra(p.getCondicionCompra());
		pv.setCuit(p.getCuit());
		pv.setDescuento(p.getDescuento());
		pv.setDireccion(p.getDireccion());
		pv.setIdProveedor(p.getIdProveedor());
		pv.setNombre(p.getNombre());
		pv.setTelefono(p.getTelefono());
		return pv;
	}
	private Proveedor buscarProveedorLocal(ProveedorVO vo)
	{
		Proveedor p;
		Iterator<Proveedor> it = proveedores.iterator();
		while(it.hasNext()){
			p= it.next();
			if(p.getCodigo() == vo.getCodigo())
			{
				return p;
			}
		}
		return null;
	}
	public Proveedor buscarProveedor(ProveedorVO vo)
	{
		// NOTA: Por ahora solo levantamos los proveedores desde base de datos
		// Proveedor p = buscarProveedorLocal(vo);
		Proveedor p = null;
		if(vo.getCodigo()!=-1) // la busqueda es por codigo
		{
			p= ProveedorDao.getInstancia().buscarProveedorXCodigo(vo.getCodigo());
//			if(p!=null)
//				proveedores.add(p);
		}
		else
		{
			if(vo.getNombre()!=null)
				p = ProveedorDao.getInstancia().buscarProveedorXNombre(vo.getNombre());
			else
			{
				if(vo.getCuit()!=null)
					p = ProveedorDao.getInstancia().buscarProveedorXCuit(vo.getCuit());
			}
		}
		return p;
	}
	
	public void bajaProveedor(ProveedorVO vo)
	{
		Iterator<Proveedor> it = proveedores.iterator();
		while(it.hasNext()){
			Proveedor p= it.next();
			if(p.getCodigo() == vo.getCodigo())
			{
				proveedores.remove(p);
			}
		}
		AdminProveedor.getInstance().borrarProveedor(vo.getCodigo());
	}
	
	public void administrarListaProveedor(){
		
	}
	
	public void generarOrdenCompraProveedor(SolicitudCompraCPR scpr)
	{
		
	}
	
	public ListaPreciosCPRVO obtenerComparativaPrecios(String codigo, String marca, String pais)
	{
		System.out.println("CPR::obtenerComparativaPrecios("+codigo+","+ marca+ "," + pais +")");
		Rodamiento r=AdminRodamiento.getInstance().buscarRodamiento(codigo);
		ArrayList<ItemListaPreciosCPRVO> items = new ArrayList<ItemListaPreciosCPRVO>();
		if(r!=null)
		{
			ArrayList<ItemListaPreciosCPR> l = AdminProveedor.getInstance().obtenerPreciosRodamiento(r,marca,pais);
			Iterator<ItemListaPreciosCPR> it = l.iterator();
			while(it.hasNext())
			{
				items.add(ItemListaPrecioCPRTOVO(it.next()));
			}
		}
		System.out.println("Cantidad de items: "+ Integer.toString(items.size()));
		ListaPreciosCPRVO lp = new ListaPreciosCPRVO("Comparativa de precios - "+ codigo,"Comparativa para codigo:"+codigo+" marca:"+ marca + "pais: "+pais,items); 
		return lp;
	}
	
	public ItemListaPreciosCPRVO ItemListaPrecioCPRTOVO(ItemListaPreciosCPR it)
	{
		return new ItemListaPreciosCPRVO(rodamientoToVO(it.getRodamiento()), it.getPrecioUnitario(), it.getMarca(), it.getOrigen(), it.getTipo(), proveedorToVO(it.getProveedor()), it.getTipoLista());
	}
	
	public ListaPreciosCPR armarComparativaPrecios()
	{
		// Creo una nueva lista de precios CPR
		ListaPreciosCPR lpcpr=new ListaPreciosCPR();

		//Obtengo todos los rodamientos existentes.
		ArrayList<Rodamiento> rod = new ArrayList<Rodamiento>( AdminRodamiento.getInstance().obtenerRodamientos());
		
		Iterator<Rodamiento>  it = rod.iterator();
		
		// Recorro los distintos rodamientos buscando cual es el mejor precio 
		while(it.hasNext())
		{
			Rodamiento rrod = it.next();
			ItemListaPreciosCPR illpCPR = AdminProveedor.getInstance().obtenerPrecioMinimoRodamiento(rrod);
			lpcpr.agregarItem(illpCPR);
		}
		//Reemplazo la lista actual
		AdminProveedor.getInstance().reemplazarListaPreciosCPR(lpcpr);
		
		return lpcpr;
	}
	
	public void setPorcentajeGanancia(Float gcia)
	{
		AdminGanacia.getInstancia().SetGanancia(gcia);
	}

private void setGanaciaListaPrecio() {
		
	
	// Para hacer.... Hernan Falta consulta HQL en el dao y hacer el admin. 
		
	}

// -- Procesar Lista de precios -- 
	
//	private ItemListaPreciosCPR obtenerMejorPrecioRodamiento(Rodamiento r)
//	{
//		AdminProveedor.getInstance().obtenerPrecioMinimoRodamiento(r);
//		return null;
//	}
	// TODO: confirmar funcion de procesamiento de Lista de precios
	public void altaItemListaPrecios(ProveedorVO pvo,String tipo, ItemListaPreciosVO vo) throws RemoteException{
		
		Proveedor p = buscarProveedor(pvo);
			
		Rodamiento ro = buscarRodamiento(vo.getRodamiento_codigo());
		p.agregarItemListaPrecios(tipo, ro, vo.getPrecioCompra(),vo.getTipo(),vo.getMarca(),vo.getOrigen());
		
		//AdminProveedor.getInstance().modificarProveedor(p);
	}
	
	public void altaListaPrecios(ProveedorVO vo, ListaPreciosVO lvo) throws Exception
	{
		Proveedor p=buscarProveedor(vo);
		if(p==null)
			throw new Exception("No se encontro el proveedor");
		
		// busco si ya tenia una lista de este tipo,.
		ListaPrecios lv= p.buscarListaPrecios(lvo.getTipo());
		if(lv != null)
			lv.setVigente(false);
			
			
		// agrego la lista nueva
		ListaPrecios l=new ListaPrecios(p,lvo.getTipo(),lvo.getFechaDesde(),lvo.getFechaHasta());
		l.setVigente(true);
		p.addListaPrecios(l);
		//AdminProveedor.getInstance().modificarProveedor(p);
	}
	
	public void confirmarListaPrecios(Proveedor p, ListaPreciosVO lvo)
	{
		ListaPrecios l =p.buscarListaPrecios(lvo.getTipo());
		// TODO: Ver como se tiene que implementar esta funcionalidad. 
		p.confirmarListaPrecios(l);
	}
	public void altaListaPrecios(ProveedorVO vo, String xml) throws Exception{
		
		ListaPreciosCPRXMLParser parser = new ListaPreciosCPRXMLParser(xml);
		
		Proveedor p=buscarProveedor(vo);
		if(p==null)
			throw new Exception("No se encontro el proveedor");
		
		// busco si ya tenia una lista de este tipo,.
		ListaPrecios lv= p.buscarListaPrecios(parser.getTipo());
		if(lv != null)
			lv.setVigente(false);
			
			
		// agrego la lista nueva
		ListaPrecios l=new ListaPrecios(p,parser.getTipo(),parser.getFechaDesde(),parser.getFechaHasta());
		l.setVigente(true);
		p.addListaPrecios(l);

		// Agrego los items.
		while(parser.hasNext())
		{
			Rodamiento ro=buscarRodamiento(parser.getCodRodamiento());
			
			p.agregarItemListaPrecios(parser.getTipo(), ro, parser.getPrecioCompra(),parser.getTipoRod(),parser.getOrigen(),parser.getMarca());
			
			parser.next();
		}
		
		p.confirmarListaPrecios(l);
	
		armarComparativaPrecios();
		setGanaciaListaPrecio();
	}

	public RodamientoVO rodamientoToVO(Rodamiento rod)
	{
		RodamientoVO rodv = new RodamientoVO();
		rodv.setId(rod.getId());
		rodv.setCodigo(rod.getCodigo());
		rodv.setDescripcion(rod.getDescripcion());
		rodv.setModelo(rod.getModelo());
		rodv.setStock(new StockVO(rod.getStock().getCantidad(), rod.getStock().getPuntoReposicion()));
		return rodv;
	}
	public ArrayList<RodamientoVO> obtenerRodamientos() {
		List<Rodamiento> r = AdminRodamiento.getInstance().obtenerRodamientos();
		ArrayList<RodamientoVO> rvo = new ArrayList<RodamientoVO>();
		
		Iterator<Rodamiento> it = r.iterator();
		while(it.hasNext())
		{
			rvo.add(rodamientoToVO(it.next()));
		}
		return rvo;
	}

	public void modificarRodamiento(Rodamiento r) {
		AdminRodamiento.getInstance().modificarRodamiento(r);
	}
	
	
	public CondicionesPagoVO condicionesPagoVO(CondicionesPago cond){
		
		String formaDePago = cond.getFormaDePago();
		float interes = cond.getInteres();
		int dias = cond.getDias();
		CondicionesPagoVO cvo = new CondicionesPagoVO(formaDePago, dias, interes);
		cvo.setIdCondicion(cond.getIdCondicion());
		return cvo;
	}
	
	
	public List<CondicionesPagoVO> getCondicionesPago() {
		List<CondicionesPago> c = AdminCondicionesPago.getInstancia().obtenerCondicionesPago();
		ArrayList<CondicionesPagoVO> rvo = new ArrayList<CondicionesPagoVO>();
		Iterator<CondicionesPago> it = c.iterator();
		while(it.hasNext()){
			rvo.add(condicionesPagoVO(it.next()));
		}
		
		
		return rvo;
	}

	public Float getPorcentajeDeGanancia() {
		return AdminGanacia.getInstancia().getPorcentajeGanacia();
	}

	public int cargarSolicitudRodamientos(String xml) {
		SolicitudRodamientos svo=new SolicitudRodamientos();
		svo.fromXml(xml);
		SolicitudRodamientoDAO.getInstancia().grabarSolicitudRodamiento(svo);
		return svo.getId();
	}
	
	
}
